// 如何判定一个对象是否为空，包括其原型链上是否有自定义函数和属性

const isEmpty = (obj: any) => {
  // null
  if (obj === null) return true;
  // undefined
  if (obj === undefined) return true;
  // 字符串
  if (typeof obj === 'string' && obj.trim() === '') return true;
  // 是数字，但不是NaN
  if (typeof obj === 'number' && isNaN(obj)) return true;
  // 是对象，且没有属性
  if (typeof obj === 'object' && Object.keys(obj).length === 0) return true;

  return false;
};

const obj = { a: () => { } };
// console.log(Object.keys(obj).length);

// 获取属性名


function IsEmptyObject(obj: any) {
  const properties = Object.getOwnPropertyNames(obj);
  // 遍历属性名
  for (const property of properties) {
    const descriptor = Object.getOwnPropertyDescriptor(obj, property);
    // 有值或者是函数
    if (
      (descriptor?.value &&
        descriptor.value !== undefined &&
        descriptor.value !== null) ||
      typeof descriptor?.value === 'function'
    ) {
      return false; // 不是空对象
    }
  }

  // 获取对象的原型
  let prototype = Object.getPrototypeOf(obj);
  // 如果有原型并且原型不是"Object.prototype"（避免误判普通对象的默认方法）
  while (prototype && prototype !== Object.prototype) {
    // 获取原型对象的属性
    const prototypeProperties = Object.getOwnPropertyNames(prototype);
    // 便利原型对象
    for (const property of prototypeProperties) {
      const descriptor = Object.getOwnPropertyDescriptor(prototype, property);
      // 有值或者是函数
      if (
        (descriptor?.value &&
          descriptor.value !== undefined &&
          descriptor.value !== null) ||
        typeof descriptor?.value === 'function'
      ) {
        return false; // 不是空对象
      }
    }
    // 继续沿着原型链向上找
    prototype = Object.getPrototypeOf(prototype);
  }
  return true;
}

const b: any = {
};
// NOTICE 这里好像有问题
b.constructor.prototype.c = 2;
console.log(IsEmptyObject(b));
